#pragma once
#include <QObject>
#include <QUdpSocket>
#include <QHostAddress>
#include <QNetworkInterface>
#include "QsUdpGlobal.h"

/**
 * @brief UDP接收器类
 * 
 * 负责在指定端口和地址上监听UDP数据包，解析数据包并发出信号。
 * 支持动态修改监听端口和地址。
 */
class QsUdpReceiver : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief 默认构造函数
     * @param parent 父对象指针，默认为nullptr
     */
    explicit QsUdpReceiver(QObject* parent = nullptr);
    
    /**
     * @brief 带参数的构造函数
     * @param info UDP信息结构体，包含端口和地址
     * @param parent 父对象指针，默认为nullptr
     */
    explicit QsUdpReceiver(const QsUdpInfo& info, QObject* parent = nullptr);
    
    /**
     * @brief 析构函数
     * 
     * 自动清理socket资源
     */
    ~QsUdpReceiver();

public slots:
    /**
     * @brief 初始化UDP接收器
     * @param info UDP信息结构体，包含端口和地址
     * 
     * 如果socket已存在，会先删除旧的socket再创建新的。
     * 使用QUdpSocket::ShareAddress和QUdpSocket::ReuseAddressHint标志。
     */
    void init(const QsUdpInfo& info);
    
    /**
     * @brief 清理资源
     * 
     * 关闭socket并释放相关资源
     */
    void cleanup();

    /**
     * @brief 设置socket选项
     * @param option 选项类型
     * @param value 选项值
     */
    void setSocketOption(QAbstractSocket::SocketOption option, const QVariant& value);

    /**
     * @brief 加入多播组
     * @param groupAddress 多播组地址
     * @param iface 网络接口，默认自动选择
     * @return 是否成功
     */
    bool joinMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface = QNetworkInterface());

    /**
     * @brief 离开多播组
     * @param groupAddress 多播组地址
     * @param iface 网络接口，默认自动选择
     * @return 是否成功
     */
    bool leaveMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface = QNetworkInterface());

    /**
     * @brief 启用或禁用广播
     * @param enabled 是否启用广播
     */
    void enableBroadcast(bool enabled);

signals:
    /**
     * @brief 接收到UDP数据包时发出的信号
     * @param header 包头
     * @param data 数据内容
     * @param info UDP信息结构体（IP和端口）
     */
    void received(const QsUdpPacketHeader& header, QByteArray data, const QsUdpInfo& info);

    /**
     * @brief 发生错误时发出的信号
     * @param msg 错误描述
     */
    void errorOccurred(const QString& msg);

    /**
     * @brief socket状态变化时发出的信号
     * @param state 新状态
     */
    void stateChanged(QAbstractSocket::SocketState state);

    /**
     * @brief 成功加入多播组时发出的信号
     * @param group 多播组地址
     */
    void multicastJoined(const QHostAddress& group);

    /**
     * @brief 广播功能启用/禁用时发出的信号
     * @param enabled 是否启用
     */
    void broadcastEnabled(bool enabled);

private slots:
    /**
     * @brief 处理socket数据可读事件
     * 
     * 当socket有数据可读时被调用，解析数据包并发出received信号
     */
    void onReadyRead();

private:
    QUdpSocket* m_socket = nullptr;    ///< UDP socket对象
    QsUdpInfo m_info;                  ///< UDP信息结构体
}; 